package cn.lijiancn01.demo.framework.util;


import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 包装 spring BeanUtils，默认复制null值
 */
public class SpringBeanUtil {

    private SpringBeanUtil() {
    }

    /**
     * 拷贝对象
     *
     * @param source
     * @param target
     * @param ignoreSourceNullField 是否忽略source上的null字段
     */
    public static void copyBean(Object source, Object target, boolean ignoreSourceNullField) {
        if (source == null) {
            return;
        }
        String[] sourceNullPropertyNames = null;
        if (ignoreSourceNullField) {
            sourceNullPropertyNames = getSourceNullPropertyNames(source);
        }
        try {
            //spring BeanUtils
            BeanUtils.copyProperties(source, target, sourceNullPropertyNames);
        } catch (Exception e) {
            throw new RuntimeException("拷贝对象异常");
        }
    }

    /**
     * 拷贝对象
     *
     * @param source
     * @param targetClass
     * @return
     */
    public static <T> T copyBean(Object source, Class<T> targetClass) {
        if (source == null) {
            return null;
        }
        T target = null;
        try {
            target = targetClass.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
        copyBean(source, target, true);

        return target;
    }

    /**
     * 拷贝对象列表
     *
     * @param sourceList  待拷贝列表
     * @param targetClass 目标类型
     * @return
     */
    public static <T> List<T> copyList(List<?> sourceList, Class<T> targetClass) {
        List<T> newList = new ArrayList<T>();
        try {
            if (CollectionUtils.isEmpty(sourceList)) {
                return newList;
            }
            for (Object source : sourceList) {
                newList.add(copyBean(source, targetClass));
            }
        } catch (Exception e) {
            throw new RuntimeException("bean list 转换异常");
        }
        return newList;
    }

    /**
     * 获取对象上为null值的属性集合
     *
     * @param source
     * @return
     */
    private static String[] getSourceNullPropertyNames(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> nullValueFieldNames = new HashSet<>();
        for (java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (null == srcValue) {
                nullValueFieldNames.add(pd.getName());
            }
        }
        String[] result = new String[nullValueFieldNames.size()];
        return nullValueFieldNames.toArray(result);
    }
}